#define _REENTRANT

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "sthread.h"
#include "sync.h"

typedef struct thread_args {
	sthread_sem_t* sem;
	int*           var;
	int            n;
} thread_args_t;

int threadmain(void* arg) {
  	thread_args_t* t_a = (thread_args_t*) arg;
	for (;;) {
	  printf("thread %d: Trying to change g_var\n", t_a->n);
	  printf("thread %d: g_var = %d\n", t_a->n, *(t_a->var));
	  fflush(stdout);
	  sthread_sem_down(t_a->sem);
	  ++(*(t_a->var));
	  printf("thread %d: Inside Semaphore - g_var = %d\n", t_a->n, *(t_a->var));
	  fflush(stdout);
	  sthread_sem_up(t_a->sem);
	}
	return 0;
}

int main(int argc, char* argv[]) {
	sthread_sem_t* g_sem = malloc(sizeof(sthread_sem_t));

	if(g_sem == NULL) {
		printf("Malloc Fail: g_sem\n");
		exit(-1);
	}

	sthread_sem_init(g_sem, 1);

	int g_var = 0;

	thread_args_t t_args_1 = {g_sem, &g_var, 1};
	thread_args_t t_args_2 = {g_sem, &g_var, 2};

	sthread_t thr1, thr2;
	if (sthread_init() == -1)
		fprintf(stdout, "%s: sthread_init: %s\n", argv[0], strerror(errno));


	if (sthread_create(&thr1, threadmain, (void*)&t_args_1) == -1)
	  fprintf(stdout, "%s: sthread_create: %s\n", argv[0], strerror(errno));
	if (sthread_create(&thr2, threadmain, (void*)&t_args_2) == -1)
	  fprintf(stdout, "%s: sthread_create: %s\n", argv[0], strerror(errno));
	
	sleep(1);
	sthread_wake(thr1);
	sleep(1);
	sthread_wake(thr2);
	sleep(1);
	sthread_wake(thr1);
	sthread_wake(thr2);
	sleep(1);

	sthread_sem_destroy(g_sem);
	
	return 0;
}
